﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using System.Diagnostics;

namespace Xml
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        private void btnReadXml_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();

            /**
             * XmlReader
             *  静态方法
             *      .Create(filePath)   创建 XmlReader 对象 
             *      .Create(TextReader) 
             *  属性
             *    .HasAttributes    节点是否有属性
             *    .AttributeCount   节点属性个数
             *  方法
             *    .Read()                   进入下一个节点
             *    .HasValue()               节点是否有值
             *    .ReadElementContentAsDecimal()    读取Element节点的强类型值,转换失败抛 FormatException
             *    .GetAttribute(i)          通过属性索引/名称获取属性值
             *    .MoveToNextAttribute()    移动到元素的下一个属性
             *    .MoveToElement()          移动到属性所属的元素
             *    
             */

            XmlReader rdr = XmlReader.Create(@"files\note.xml");
            while (rdr.Read())
            {
                // 读取文本节点的值
                // if (rdr.NodeType == XmlNodeType.Text)
                //    richTextBox1.AppendText(rdr.Value + Environment.NewLine); // 文本节点才有 Value

                // 读取Element节点的强类型值
                // if(rdr.NodeType == XmlNodeType.Element && rdr.Name == "fitemid")
                //    richTextBox1.AppendText("decimal value:" + rdr.ReadElementContentAsDecimal().ToString() + Environment.NewLine);

                // 读取Element的节点
                /*
                    if (rdr.NodeType == XmlNodeType.Element && rdr.AttributeCount > 0)
                    {
                        while (rdr.MoveToNextAttribute())
                            richTextBox1.AppendText( "name: " + rdr.Name + " value: " + rdr.Value + Environment.NewLine);

                        rdr.MoveToElement();    // 移回 Element
                    }
                */

                // 读取节点属性 二
                if (rdr.HasAttributes)
                {
                    for (int i = 0; i < rdr.AttributeCount; i++)
                    {
                        richTextBox1.AppendText(rdr.GetAttribute(i) + Environment.NewLine);
                    }
                }

            }

        }


        private void setting_ValidationEventHandler(object sender, ValidationEventArgs e)
        {
            // 事件由警告/错误触发
            if (e.Severity == XmlSeverityType.Warning)
                MessageBox.Show("Warning: " + e.Message);
            else
                MessageBox.Show("Error: " + e.Message);
        }

        private void btnValidateXml_Click(object sender, EventArgs e)
        {
            /**
             * 如果xml根元素的xlmns值不等于xsd的targetNameSpace, 则不会进行验证. 所以要测试验证两者必须一致。
             * 如果监听 ValidationEvent 验证错误会抛出异常 XmlSchemaValidationException
             */

            XmlReaderSettings setings = new XmlReaderSettings();
            setings.Schemas.Add(null, XmlReader.Create(new StringReader(richTextBox1.Text)));
            setings.ValidationType = ValidationType.Schema;
            setings.ValidationEventHandler += setting_ValidationEventHandler;


            XmlReader rdr = XmlReader.Create(new StringReader(richTextBox2.Text), setings);
            while (rdr.Read())
            {
                if (rdr.HasValue)
                {
                    Debug.WriteLine(rdr.Value);
                }
            }
        }

        // 快速、非缓存和只进的方式来生成包含 XML 数据的流或文件
        private void btnWriteXml_Click(object sender, EventArgs e)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            // settings.NewLineOnAttributes = true;
            settings.Indent = true;

            XmlWriter w = XmlWriter.Create(@"d:\\x.xml", settings);
            w.WriteStartDocument();
            w.WriteStartElement("order");
            w.WriteAttributeString("billno", "XC20130607");
            w.WriteEndElement();
            w.WriteEndDocument();
            w.Flush();
            w.Close();
        }

        /**
         * XmlDocument
         *      .DocumentElement                        xml文档的根节点
         * 
         *      .GetElementsByTagName(string tagName)    获取指定标签组成的  XmlNodeList
         *      
         *      .CreateElement(name)                     创建元素
         *      .CreateAttribute(name)
         *      .CreateComment(data)
         *      .CreateTextNode(text)
         *      
         *      .Load(path)                             从指定路径加载 xml 
         *      .LoadXml(text)                          从指定字符串加载 xml
         *      
         *      .Validate(ValidationEventHandler)       使用 Schemas 属性中架构验证节点
         * 
         * XmlElement
         *      GetAttribute(name)                      获取指定名称属性的值
         *      SetAttribute(name, value)
         *      RemoveAttribute(name)
         *      GetAttributeNode(name)                  获取指定名称属性的节点对象 XmlAttribute
         * 
         * XmlAttribute     
         *      .OwnerElement                           属性所属Element 
         * 
         * XmlNodeList
         *      .Count              节点数量
         *      .Item(int index)    获取指定索引的节点
         * 
         * XmlNode
         *      .Atributes                  返回节点的属性集合 XmlAttributeColection
         *      .ChildNodes                 返回子节点组成的 XmlNodeList
         *      .FirstChild             
         *      .LastChild
         *      .ParentNode
         *      .HasChildNodes
         *      
         *      .InnerText                  返回当前节点及所有子节点的文本节点连接起来的字符串
         *      .InnerXml                   返回子节点的xml元素文本
         *      .OuterXml                   返回节点及子节点的元素文本
         *      .Value                      节点的值
         * 
         *      .SelectNodes(xpath)         获取匹配 xpath 的 XmlNodeList
         *      .SlectSingleNode(xpaht)     获取匹配 xpath 的第一个 XmlNode
         *      
         *      .NodeType                   节点类型  XmlNodeType   Element, Attribute, Text, Document, Comment
         *  
         *      
         *      .AppendChild(XmlNode n)             添加 XmlNode 到子节点末尾
         *      .PrependChild(XmlNode n)
         *      .InsertAfert(newChild, oldChild)
         *      .InsertBefore(newChild, oldChild)
         *      .RemoveAll()                        移除所有子节点,属性节点
         *      .Remove(oldChild)                   
         *      .ReplaceChild(newChild, oldChild)
         *      
         *      .WriteContentTo(XmlWriter w)        保存子节点到 w
         *      .Write(XmlWriter w)                 保存当前节点到 w
         *    
         */

        // 读取 xml
        private void btnXmlDocumentLoadFile_Click(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(@"files/example.xml");

            XmlNodeList nodeList = doc.GetElementsByTagName("from");
            foreach (XmlNode node in nodeList)
            {
                richTextBox3.AppendText(node.OuterXml + Environment.NewLine);
            }
        }

        /**
         * 读取 xml - xpath
         * 
         *      xpath 几个常用例子
         *          /n:note/n:to                根节点下面note元素下面的to元素
         *          //n:to//attribute::lang     to元素的lang属性节点
         *          //n:to//child::text()       to元素的文本节点
         *
         * 
                <?xml version="1.0"?>
                <note xmlns="http://www.w3school.com.cn">
                    <to>George</to>
                    <from>John</from>
                    <heading>Reminder</heading>
                    <body>Don't forget the meeting!</body>
                </note>
        */
        private void btnXpath_Click(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(new StringReader(richTextBox2.Text));
            XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
            xnm.AddNamespace("n", @"http://www.w3school.com.cn");   // 关于命名空间,前缀  http://www.w3school.com.cn/xml/xml_namespaces.asp
            XmlNode node = doc.SelectSingleNode(txtXpath.Text, xnm);
            if (node != null)
            {
                richTextBox3.Text = node.OuterXml + Environment.NewLine;
                richTextBox3.AppendText(DateTime.Now.ToString("YY-MM-dd HH:mm:ss"));
            }
            else
            {
                richTextBox3.Text = "none" + Environment.NewLine;
                richTextBox3.AppendText(DateTime.Now.ToString("YY-MM-dd HH:mm:ss"));
            }
        }

        /**
         * 插入 XmlElment 到 XmlDocument
         */
        private void btnInsertElement_Click(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(@"files\example.xml");
            XmlElement el = doc.CreateElement("attatch");
            el.SetAttribute("filename", "good.gif");
            el.InnerText = @"d:\good.gif";
            doc.DocumentElement.AppendChild(el);

            richTextBox3.Text = doc.OuterXml;
        }


        /**
         * DataSet
         *      .WriteXml(stream)                               写入DataSet的xml格式数据 data
         *      .WriteXml(steam, XmlWriteMode.WriteSchema)      写入DataSet的xml data, Schema
         *      .WriteXmlSchema(steam/path)                     写入DataSet的xml schema
         *      .ReadXml(stream/path)                           从xml文件读取data,schema到DataSet
         *      .ReadXmlSchema(stream/path)                     从xml文件读取schema
         * 
         * XmlDataDocument 继承于XmlDocument, 区别是可从DataSet加载xml数据
         *      new XmlDataDocument(DataSet)                    更简单的从DataSet加载xml
         * 
         */
        private void btnDataSet2Xml_Click(object sender, EventArgs e)
        {

            SqlConnection cnn = new SqlConnection("Server=127.0.0.1,1433;User ID=sa;Pwd=colin;Initial Catalog=lhbdt;");
            SqlCommand cmd = cnn.CreateCommand();
            cmd.CommandText = "select fitemid,fname,fnumber from t_emp";

            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet("k3");
            da.Fill(ds, "t_emp");

            // DataSet 2 xml
            ds.WriteXml(@"d:\emp.xml");
            ds.WriteXml(@"d:\emp.schema.xml", XmlWriteMode.WriteSchema);
            ds.WriteXmlSchema(@"d:\schema.xml");

            // DataSet 2 xml 使用 XmlDataDocument
            XmlDataDocument doc = new XmlDataDocument(ds);
            XmlWriterSettings writerSetting = new XmlWriterSettings();
            writerSetting.Indent = true;
            XmlWriter w = XmlWriter.Create(@"d:\doc.xml", writerSetting);
            doc.Save(w);

        }

        private void btnXml2DataSet_Click(object sender, EventArgs e)
        {
            DataSet ds = new DataSet();
            ds.ReadXml(@"files\emp.xml");
            dataGridView1.DataSource = ds.Tables[0];
        }
    }
}
